#############################################################################
##
## Copyright (C) 2006-2006 Mindcast Productions. All rights reserved.
##
## This file is part of the Universal SQL Navigator - UniSQLNav.
## Find more information in: http://code.google.com/p/unisqlnav/
## Contact at carlosedp@gmail.com
##
## This file may be used under the terms of the GNU General Public
## License version 2.0 as published by the Free Software Foundation
## and appearing in the file LICENSE.GPL included in the packaging of
## this file.  Please review the following information to ensure GNU
## General Public Licensing requirements will be met:
## http://www.gnu.org/licenses/gpl.txt
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
## $Rev: $
## $Date: $
##
#############################################################################

import sys
import psyco

from PyQt4 import QtCore, QtGui

from conf.releaseinfo import *
from utils import QTUtilities
from ui_UniSQLNav import Ui_MainWindow
from ui.sqlWindow import sqlWindow
from ui.sessionWindow import sessionWindow

psyco.full()

#--- Application Start

class mainWindow(QtGui.QMainWindow, Ui_MainWindow):

    openwindowsNames = {}
    openwindowsInstances = {}

    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        # Set up the user interface from Designer.
        self.setupUi(self)
        self.workspace = QtGui.QWorkspace()
        self.setCentralWidget(self.workspace)

        self.setWindowTitle(PROJECTNAME + " " + VERSION)

        self.windowMapper = QtCore.QSignalMapper(self)
        self.connect(self.windowMapper, QtCore.SIGNAL("mapped(QWidget *)"),
                     self.workspace, QtCore.SLOT("setActiveWindow(QWidget *)"))

        self.readSettings()
        self.configureActions()

        self.openSessions = {}
        QTUtilities.makeMenuAction(self.objectTree, "Open Session", self.actionSessions_Clicked)
        QTUtilities.makeMenuAction(self.objectTree, "Close Session", self.treeRemoveSession)

        self.statusdiv = QtGui.QFrame(self.statusbar)
        self.statusdiv.setObjectName("statusline")
        self.statusbar.addPermanentWidget(self.statusdiv)

    def readSettings(self):
        settings = QtCore.QSettings(COMPANY, CONDENSEDNAME)
        pos = settings.value("mainpos", QtCore.QVariant(QtCore.QPoint(150, 150))).toPoint()
        size = settings.value("mainsize", QtCore.QVariant(self.size())).toSize()
        state = settings.value("state").toByteArray ()
        self.move(pos)
        self.resize(size)
        self.restoreState(state)

    def writeSettings(self):
        settings = QtCore.QSettings(COMPANY, CONDENSEDNAME)
        settings.setValue("mainpos", QtCore.QVariant(self.pos()))
        settings.setValue("mainsize", QtCore.QVariant(self.size()))
        settings.setValue("state", QtCore.QVariant(self.saveState()))

    def configureActions(self):
        # Toolbar actions
        self.connect(self.actionSessions, QtCore.SIGNAL("triggered()"),self.actionSessions_Clicked)
        self.connect(self.actionObject_Tree, QtCore.SIGNAL("triggered()"),self.actionObject_Tree_Clicked)
        self.connect(self.actionNew_SQL_Window, QtCore.SIGNAL("triggered()"),self.actionNew_SQL_Window_Clicked)
        self.connect(self.actionNew_SQL_WindowButton, QtCore.SIGNAL("triggered()"),self.actionNew_SQL_Window_Clicked)
        self.connect(self.objectTree, QtCore.SIGNAL("itemDoubleClicked(QTreeWidgetItem *,int)"),self.openSQLWindow)

        self.actionObject_Tree.setCheckable(True)
        self.actionObject_Tree.setChecked(True)
        self.objectTree.header().hide()
        self.configureMenuActions()


    def treeAddSession(self, session, session_data):
        self.openSessions[session_data['name']] = {'session': session,
                                                   'session_data': session_data}
        self.objectTree.setColumnCount(2)
        self.objectTree.setColumnHidden(1, True)
        root = QtGui.QTreeWidgetItem(self.objectTree)
        root.setText(0, session_data['name'] + ' - ' + session_data['driver'])
        root.setText(1, 'root')
        root.setIcon(0,QtGui.QIcon(":/treeicons/img/session_tree.png"))
        tableObj = QtGui.QTreeWidgetItem(root)
        tableObj.setText(0,'Tables')
        tableObj.setText(1, 'tableroot')
        tableObj.setIcon(0,QtGui.QIcon(":/treeicons/img/table_tree.png"))
        viewObj = QtGui.QTreeWidgetItem(root)
        viewObj.setText(0,'Views')
        viewObj.setText(1, 'viewroot')
        viewObj.setIcon(0,QtGui.QIcon(":/treeicons/img/view_tree.png"))

        for table in session.getTables():
            tableItem = QtGui.QTreeWidgetItem(tableObj, [table[0],])
            tableItem.setIcon(0,QtGui.QIcon(":/treeicons/img/table_tree.png"))
            indexObj = QtGui.QTreeWidgetItem(tableItem)
            indexObj.setText(0,'Indexes')
            indexObj.setText(1, 'indexroot')
            indexObj.setIcon(0,QtGui.QIcon(":/treeicons/img/index_tree.png"))
            for index in session.getIndexes(table[0]):
                indexItem = QtGui.QTreeWidgetItem(indexObj, [index[0],])
                indexItem.setIcon(0,QtGui.QIcon(":/treeicons/img/index_tree.png"))

            triggerObj = QtGui.QTreeWidgetItem(tableItem)
            triggerObj.setText(0,'Triggers')
            triggerObj.setText(1, 'triggerroot')
            triggerObj.setIcon(0,QtGui.QIcon(":/treeicons/img/trigger_tree.png"))
            for trigger in session.getTriggers(table[0]):
                triggerItem = QtGui.QTreeWidgetItem(triggerObj, [trigger[0],])
                triggerItem.setIcon(0,QtGui.QIcon(":/treeicons/img/trigger_tree.png"))

        for view in session.getViews():
            viewItem = QtGui.QTreeWidgetItem(viewObj, [view[0],])
            viewItem.setIcon(0,QtGui.QIcon(":/treeicons/img/view_tree.png"))
            indexObj = QtGui.QTreeWidgetItem(viewItem)
            indexObj.setText(0,'Indexes')
            indexObj.setText(1, 'indexroot')
            indexObj.setIcon(0,QtGui.QIcon(":/treeicons/img/index_tree.png"))
            for index in session.getIndexes(view[0]):
                indexItem = QtGui.QTreeWidgetItem(indexObj, [index[0],])
                indexItem.setIcon(0,QtGui.QIcon(":/treeicons/img/index_tree.png"))

            triggerObj = QtGui.QTreeWidgetItem(viewItem)
            triggerObj.setText(0,'Triggers')
            triggerObj.setText(1, 'triggerroot')
            triggerObj.setIcon(0,QtGui.QIcon(":/treeicons/img/trigger_tree.png"))
            for trigger in session.getTriggers(view[0]):
                triggerItem = QtGui.QTreeWidgetItem(triggerObj, [trigger[0],])
                triggerItem.setIcon(0,QtGui.QIcon(":/treeicons/img/trigger_tree.png"))

    def treeRemoveSession(self):
        if self.objectTree.selectedItems():
            top = self.objectTree.indexOfTopLevelItem(self.getroot(self.objectTree.selectedItems()[0]))
            self.objectTree.takeTopLevelItem(top)

    def getroot(self, item):
        if item.text(1) == 'root':
            return item
        if str(item.text(1)) != 'root':
            return self.getroot(item.parent())
        else:
            return item

    def openSQLWindow(self, item, col):
        if not str(item.text(1)).endswith('root'):
            sessname = str(self.getroot(item).text(0))
            root = sessname.split(' - ')[0]
            session = self.openSessions[root]['session']
            self.openWindow(sqlWindow, session, sessname, item.text(0))

    # Toolbar items functions
    def actionSessions_Clicked(self):
        self.openWindow(sessionWindow)

    def actionObject_Tree_Clicked(self):
        if self.objectDock.toggleViewAction().isChecked():
            self.objectDock.close()
            self.actionObject_Tree.setChecked(False)
        else:
            self.objectDock.show()
            self.actionObject_Tree.setChecked(True)

    def actionNew_SQL_Window_Clicked(self):
        if self.objectTree.selectedItems():
            item = self.objectTree.selectedItems()[0]
            root = str(self.getroot(item).text(0))
            session = self.openSessions[root]['session']
            if item.text(1) == 'root':
                object = ''
            else:
                object = item.text(0)
            self.openWindow(sqlWindow, session, root, object)

    def openWindow(self, window, *args, **kwargs):
        if window in self.openwindowsNames and repr(window) != "<class 'ui.sqlWindow.sqlWindow'>":
            self.workspace.setActiveWindow(self.openwindowsNames[window])
        else:
            internal_window = window(self, *args, **kwargs)
            self.workspace.addWindow(internal_window)   # Adds window to workspace
            internal_window.show()
            self.openwindowsNames.update({window: internal_window})
            self.openwindowsInstances.update({internal_window: window})
            #return internal_window

    # Event functions
    def closeEvent(self, event):
        event.accept()
        self.programExit()

    # Application functions
    def programExit(self):
        self.writeSettings()
        self.workspace.closeAllWindows()
        sys.exit()

    # Menu items functions
    def programHelp(self):
        # TODO: Create program help
        QtGui.QMessageBox.about(self, self.tr(PROJECTNAME + " Help"),
            self.tr("Displays the program help"))

    def programAbout(self):
        # TODO: Create program about
        QtGui.QMessageBox.about(self, self.tr("About " + CONDENSEDNAME),
            self.tr(PROJECTNAME + "\nVersion ")+ VERSION + "\nBuild $Rev: $")

    def configureMenuActions(self):
        # Menus
        self.connect(self.actionE_xit, QtCore.SIGNAL("triggered()"), self.programExit)
        self.connect(self.action_Help, QtCore.SIGNAL("triggered()"), self.programHelp)
        self.connect(self.actionAbout, QtCore.SIGNAL("triggered()"), self.programAbout)
        self.connect(self.windowMenu, QtCore.SIGNAL("aboutToShow()"), self.updateWindowMenu)

        # Menu Actions
        self.closeAct = QtGui.QAction(self.tr("Cl&ose"), self)
        self.closeAct.setShortcut(self.tr("Ctrl+F4"))
        self.closeAct.setStatusTip(self.tr("Close the active window"))
        self.connect(self.closeAct, QtCore.SIGNAL("triggered()"),
                     self.workspace.closeActiveWindow)

        self.closeAllAct = QtGui.QAction(self.tr("Close &All"), self)
        self.closeAllAct.setStatusTip(self.tr("Close all the windows"))
        self.connect(self.closeAllAct, QtCore.SIGNAL("triggered()"),
                     self.workspace.closeAllWindows)

        self.tileAct = QtGui.QAction(self.tr("&Tile"), self)
        self.tileAct.setStatusTip(self.tr("Tile the windows"))
        self.connect(self.tileAct, QtCore.SIGNAL("triggered()"), self.workspace.tile)

        self.cascadeAct = QtGui.QAction(self.tr("&Cascade"), self)
        self.cascadeAct.setStatusTip(self.tr("Cascade the windows"))
        self.connect(self.cascadeAct, QtCore.SIGNAL("triggered()"),
                     self.workspace.cascade)

        self.arrangeAct = QtGui.QAction(self.tr("Arrange &icons"), self)
        self.arrangeAct.setStatusTip(self.tr("Arrange the icons"))
        self.connect(self.arrangeAct, QtCore.SIGNAL("triggered()"),
                     self.workspace.arrangeIcons)

        self.nextAct = QtGui.QAction(self.tr("Ne&xt"), self)
        self.nextAct.setShortcut(self.tr("Ctrl+F6"))
        self.nextAct.setStatusTip(self.tr("Move the focus to the next window"))
        self.connect(self.nextAct, QtCore.SIGNAL("triggered()"),
                     self.workspace.activateNextWindow)

        self.previousAct = QtGui.QAction(self.tr("Pre&vious"), self)
        self.previousAct.setShortcut(self.tr("Ctrl+Shift+F6"))
        self.previousAct.setStatusTip(self.tr("Move the focus to the previous "
                                              "window"))
        self.connect(self.previousAct, QtCore.SIGNAL("triggered()"),
                     self.workspace.activatePreviousWindow)

        self.separatorAct = QtGui.QAction(self)
        self.separatorAct.setSeparator(True)

    # Builds the "window" menu with all open windows
    def updateWindowMenu(self):
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.tileAct)
        self.windowMenu.addAction(self.cascadeAct)
        self.windowMenu.addAction(self.arrangeAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.workspace.windowList()
        self.separatorAct.setVisible(len(windows) != 0)
        i = 0
        for child in windows:
            if i < 9:
                text = self.tr("&%1 %2").arg(i + 1).arg(child.windowTitle())
            else:
                text = self.tr("%1 %2").arg(i + 1).arg(child.windowTitle())
            i += 1

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child == self.activeMdiChild())
            self.connect(action, QtCore.SIGNAL("triggered()"),
                         self.windowMapper, QtCore.SLOT("map()"))
            self.windowMapper.setMapping(action, child)

    def activeMdiChild(self):
        return self.workspace.activeWindow()

#--- Runs the main app

def main():
    app = QtGui.QApplication(sys.argv)
    mainwindow = mainWindow()
    mainwindow.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()